package com.wutong.eams.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;

@Slf4j
public class ObjectUtil {

    private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 通过map填充对象属性，需要对象类符合JavaBean规范
     * @param obj 要填充的对象
     * @param map 要填充的map
     * @param ignoreUnmatched 是否忽略map中没有对应属性的字段
     * @return
     * @param <T>
     */
    public static<T> T fillObjectFromMap(T obj, Map<String, Object> map, boolean ignoreUnmatched) {
        String unknowKey = "";
        try {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                key = StringUtil.convertCamel(key);
                Object value = entry.getValue();

                // 添加日期类型转换
                if (value instanceof LocalDateTime || value instanceof LocalDate) {
                    if (value instanceof LocalDateTime ldt) {
                        value = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
                    } else {
                        LocalDate ld = (LocalDate) value;
                        value = Date.from(ld.atStartOfDay(ZoneId.systemDefault()).toInstant());
                    }
                }

                Class<?> clazz = obj.getClass();
                unknowKey = key;
                Field field = clazz.getDeclaredField(key);
                field.setAccessible(true);
                field.set(obj, value);
            }
        } catch (NoSuchFieldException e) {
            if (!ignoreUnmatched) {
                log.error("对象类中没有{}属性", unknowKey, e);
                throw new IllegalArgumentException("对象类中没有" + unknowKey + "属性");
            } else {
                log.warn("对象类中没有{}属性", unknowKey, e);
                map.remove(unknowKey);
                return fillObjectFromMap(obj, map, true);
            }
        } catch (Exception e) {
            log.error("填充对象属性失败", e);
            throw new IllegalArgumentException("填充对象属性失败");
        }
        return obj;
    }

    public static String convertEntityToJson(Object obj) {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("转换对象为json失败", e);
            throw new IllegalArgumentException("转换对象为json失败");
        }
    }

    public static <T> T convertJsonToEntity(String json, Class<T> clazz) {
        try {
            return new Gson().fromJson(json, clazz);
        } catch (Exception e) {
            log.error("转换json为对象失败", e);
            throw new IllegalArgumentException("转换json为对象失败");
        }
    }

    public static <T> T copyProperties(T source, T target, boolean ignoreNull) {
        try {
            Field[] fields = source.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Object value = field.get(source);
                if (ignoreNull && value == null) {
                    continue;
                }
                field.set(target, value);
            }
            return target;
        } catch (Exception e) {
            log.error("复制对象属性失败", e);
            throw new IllegalArgumentException("复制对象属性失败");
        }
    }

    public static String toJson(Object obj) {
        return new Gson().toJson(obj);
    }

}
